' This program exported from BASIC Anywhere Machine (Version [5.2.3].[2024.09.09.00.00]) on 2024.12.26 at 04:11 (Coordinated Universal Time)
_TITLE "Saucer Zap"
' BAM port and mod by Charlie Veniot
' of the QBJS by James D. Jarvis, it a mod
' of Plasma Laser Canon demo prep for GUI 2020-11-11
OPTION EXPLICIT
OPTION BASE 1
_INITAUDIO
SCREEN _NEWIMAGE( 1200, 600, 32 )
ALERT( "Click/touch the screen to shoot your spaceship's plasma laser canon at that coordinate." _
+ "\n\n The plasma laser cannon has a limited range, so will not shoot if you click/touch the screen too far away." _
+ "\n\n Moving the ship requires a physical keyboard: [W] for up [S] for down [A] for left [D] for right." _
+ "\n\n Each attack wave will have an increasing number of spaceships.")
'🟠🟠🟠 DECLARE VARIABLES
DIM AS LONG ShipLights
DIM AS ULONG ShipColor
DIM AS LONG cx, cy, mx, my, mb, sx, sy, ix, iy, killflag, x, score
DIM AS SINGLE ma, md, dx, dy, damage, cdiv
DIM AS INTEGER targetx(50), targety(50), targetvx(50), targetvy(50), targetalive(50), targets, targetsDestroyed
DIM targetcolor(50) AS ULONG
DIM w%, i%, ik$
'🟠🟠🟠 DECLARE SUBROUTINES
DECLARE SUB PLC( baseX, baseY, targetX, targetY, targetR )
DECLARE SUB drawShip(x, y, colr AS ULONG )
DECLARE SUB drawtarget( x, y, colr AS ULONG )
DECLARE SUB fcirc( CX AS LONG, CY AS LONG, R AS LONG )
DECLARE SUB fEllipse( CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG )
'🟠🟠🟠 MAIN PROGRAM
cy = INT( _HEIGHT / 2 ) : cx = INT( _WIDTH / 2 )
ShipColor = &HFF3366AA
🏁🏁🏁ProgramStart🏁🏁🏁:
LET sx = cx, sy = cy, _
mx = 0, my = 0, mb = 0, ix = 0, iy = 0, killflag = 0, x = 0, score = 0, _
ma = 0, md = 0, dx = 0, dy = 0, damage = 0, cdiv = 0, _
targets = 2, targetsDestroyed = 0
GOSUB A100_🎯ResetTargets
DO
CLS
GOSUB A200_🔤CheckKeyboard
GOSUB A300_🖱CheckMouse
CALL drawShip( sx, sy, ShipColor )
GOSUB F100_💥DoWeaponFiring
GOSUB F200_🛸MoveTargets
GOSUB F300_☠DoShipBoom
'' IF killflag = 13 THEN LOCATE ( sy - ( sy MOD 16 )) / 16 , MIN( ( sx - ( sx MOD 8 )) / 8, _WIDTH / 8 - 8) : _ENDAUDIO : SOUND 325, 5 : COLOR _RGB32( 255, 255, 0 ) : PRINT " BOOM!!!! "
_DISPLAY
SLEEP 0.01
LOOP UNTIL killflag = 13
GOSUB Z100_🛑GameOver
GOTO 🏁🏁🏁ProgramStart🏁🏁🏁
END
'🟠🟠🟠 GOSUB SUBROUTINES
A100_🎯ResetTargets:
FOR i% = 1 TO targets
DO
IF INT( RND * 2 ) = 0 _
THEN : targetx(i%) = INT( RND * _WIDTH ) : targety(i%) = CHOOSE( INT( RND * 2 ) + 1, 0, YMAX )
ELSE : targety(i%) = INT( RND * _HEIGHT ) : targetx(i%) = CHOOSE( INT( RND * 2 ) + 1, 0, XMAX )
END IF
targetvx(i%) = INT( RND * 2 ) - INT( RND * 2 )
targetvy(i%) = INT( RND * 2 ) - INT( RND * 2 )
targetcolor(i%) = _RGB32( INT( 100 + RND * 150 ), _
INT( 100 + RND * 150 ), _
INT( 100 + RND * 150 ) )
targetalive(i%) = 10
LOOP UNTIL INT( targetx(i%) / 30 ) <> INT( sx / 20 ) _
AND INT( targety(i%) / 30 ) <> INT( sy / 30 )
NEXT i%
sx = cx
sy = cy
RETURN
A200_🔤CheckKeyboard:
ik$ = INKEY$
SELECT CASE ik$
CASE "W", "w"
iy = IFF( sy - 30 >= 0, iy - 4, iy )
ix = 0
CASE "A", "a"
iy = 0
ix = IFF( sx - 50 >= 0, ix - 4, ix )
CASE "S", "s"
iy = IFF( sy + 30 <= YMAX, iy + 4, iy )
ix = 0
CASE "D", "d"
iy = 0
ix = IFF( sx + 50 <= XMAX, ix + 4, ix )
END SELECT
RETURN
A300_🖱CheckMouse:
GETMOUSE mx, my, w%, mb
dx = mx - sx ' ship avoids collision with mouse
dy = my - sy
ma = _ATAN2( dy, dx )
md = SQR( dy * dy + dx * dx )
IF md < 80 THEN md = 80
sx = sx + ix
sy = sy + iy
ix = ix / 2
iy = iy / 2
RETURN
F100_💥DoWeaponFiring:
IF mb AND md < 301 THEN
CALL PLC(sx, sy, mx, my, 10 ) : _ENDAUDIO : SOUND 25,1
ShipColor = _RGB32( INT( RND * 100 ) + 150, _
INT( RND * 100 ) + 150, _
INT( RND * 100 ) + 150 )
FOR x = 1 TO targets
IF INT( targetx(x) / 20 ) = INT( mx / 20 ) AND INT( targety(x) / 20 ) = INT( my / 20 ) AND targetalive(x) > 0 THEN
damage = 1 + ABS( 10 - INT( RND * SQR(md) ) )
targetalive(x) = targetalive(x) - damage
cdiv = ( 20 - targetalive(x) ) / 2
targetcolor(x) = _RGB32( INT( RND * ( 100 / cdiv ) ) + ( 150 / cdiv ), _
INT( RND * ( 100 / cdiv ) ) + ( 150 / cdiv ), _
INT( RND * ( 100 / cdiv ) ) + ( 150 / cdiv ) )
_ENDAUDIO : SOUND 95,5
IF targetalive(x) <= 0 THEN score += 1 : targetsDestroyed += 1
IF targetsDestroyed = targets THEN targets += IFF( targets <= 47, 3, 0 ) : targetsDestroyed = 0 : GOSUB A100_🎯ResetTargets
END IF
NEXT x
END IF
RETURN
F200_🛸MoveTargets:
FOR i% = 1 TO targets
targetx(i%) = targetx(i%) + targetvx(i%)
targety(i%) = targety(i%) + targetvy(i%)
IF INT( targetx(i%) / 30 ) = INT( sx / 30 ) AND INT( targety(i%) / 20 ) = INT( sy / 20 ) AND targetalive(i%) > 0 THEN killflag = 13
IF RND * 100 < 30 THEN
SELECT CASE INT( RND * 20 )
CASE 1, 2, 3 'seek ship
IF targetx(i%) < sx THEN targetvx(i%) = 2
IF targetx(i%) > sx THEN targetvx(i%) = -2
IF targety(i%) < sx THEN targetvy(i%) = 2
IF targety(i%) > sx THEN targetvy(i%) = -2
CASE 4, 5 'flee ship
IF targetx(i%) < sx THEN targetvx(i%) = -2
IF targetx(i%) > sx THEN targetvx(i%) = 2
IF targety(i%) < sx THEN targetvy(i%) = -2
IF targety(i%) > sx THEN targetvy(i%) = 2
CASE 7 'rando change
targetvy(i%) = targetvy(i%) + INT( RND * 3 ) - INT( RND * 3 )
targetvx(i%) = targetvx(i%) + INT( RND * 3 ) - INT( RND * 3 )
END SELECT
END IF
IF targetx(i%) < -20 THEN targetx(i%) = XMAX
IF targetx(i%) > XMAX + 20 THEN targetx(i%) = 0
IF targety(i%) < -20 THEN targety(i%) = YMAX
IF targety(i%) > YMAX + 20 THEN targety(i%) = 0
IF targetalive(i%) > 0 THEN CALL drawtarget( targetx(i%), targety(i%), targetcolor(i%) )
NEXT i%
RETURN
F300_☠DoShipBoom:
IF killflag = 13 _
THEN LOCATE ( sy - ( sy MOD 16 )) / 16 , MIN( ( sx - ( sx MOD 8 )) / 8, _WIDTH / 8 - 8) : _
_ENDAUDIO : SOUND 325, 5 : _
COLOR _RGB32( 255, 255, 0 ) : _
PRINT " BOOM!!!! "
RETURN
Z100_🛑GameOver:
_AUTODISPLAY
_DELAY 1
CLS
COLOR _RGB32(255, 255, 0)
_ENDAUDIO
SOUND 55, 5 : SOUND 45, 5 : SOUND 55, 5
PRINT : PRINT "GAME OVER"
PRINT : PRINT "Score "; (score * score) * 1000
PRINT : PRINT "Press any key or click the screen to start a new game"
SLEEP
CLS
RETURN
'🟠🟠🟠 SUB DEFINITIONS
SUB PLC( baseX, baseY, targetX, targetY, targetR ) ' PLC for PlasmaLaserCannon
DIM r, g, b, hp, ta, dist, dr, x, y, c, rr
r = RND ^ 2 * RND: g = RND ^ 2 * RND: b = RND ^ 2 * RND: hp = _PI(.5) ' red, green, blue, half pi
ta = _ATAN2( targetY - baseY, targetX - baseX ) ' angle of target to cannon base
dist = SQR( [ ( targetX - baseX ) ^ 2 ] + [ ( targetY - baseY ) ^ 2 ] ) ' distance cannon to target
dr = targetR / dist
FOR r = 0 TO dist STEP .25
x = baseX + r * COS(ta)
y = baseY + r * SIN(ta)
c = c + .3
COLOR _RGB32( 128 + 127 * SIN( r * c ), _
128 + 127 * SIN( g * c ), _
128 + 127 * SIN( b * c ) )
CALL fcirc( x, y, dr * r )
NEXT
FOR rr = dr * r TO 0 STEP -.5
c = c + 1
COLOR _RGB32( 128 + 127 * SIN( r * c ), _
128 + 127 * SIN( g * c ), _
128 + 127 * SIN( b * c ) )
CALL fcirc( x, y, rr )
NEXT rr
END SUB
SUB drawShip( x, y, colr AS ULONG ) 'shipType collisions same as circle x, y radius = 30
' shared here ShipLights
DIM AS LONG light, r, g, b
r = _RED(colr) : g = _GREEN(colr) : b = _BLUE(colr)
COLOR _RGB32( r, g - 120, b - 100 )
CALL fEllipse( x, y, 6, 15 )
COLOR _RGB32( r, g - 60, b - 50 )
CALL fEllipse ( x, y, 18, 11 )
COLOR _RGB32( r, g, b )
CALL fEllipse ( x, y, 30, 7 )
FOR light = 0 TO 5
COLOR _RGB32( ShipLights * 50, ShipLights * 50, ShipLights * 50 )
CALL fcirc( x - 30 + 11 * light + ShipLights, y, 1 )
NEXT light
ShipLights = IFF( ShipLights + 1 > 5, 0, ShipLights + 1 )
END SUB
SUB drawtarget( x, y, colr AS ULONG ) 'shipType collisions same as circle x, y radius = 30
' shared here ShipLights
DIM AS LONG light, r, g, b
r = _RED(colr) : g = _GREEN(colr) : b = _BLUE(colr)
COLOR _RGB32( r, g - 120, b - 100 )
CALL fEllipse( x, y, 3, 15 )
COLOR _RGB32( r, g - 60, b - 50 )
CALL fEllipse( x, y, 9, 11 )
COLOR _RGB32( r, g, b )
CALL fEllipse( x, y, 15, 7 )
FOR light = 1 TO 3
COLOR _RGB32( ShipLights * 50, ShipLights * 50, ShipLights * 50 )
CALL fcirc( x - 30 + 11 * light + ShipLights, y, 1 )
NEXT light
ShipLights = IFF( ShipLights + 1 > 5, 0, ShipLights + 1 )
END SUB
SUB fcirc( CX AS Long, CY AS LONG, R AS LONG )
DIM AS LONG subRadius, RadiusError, X, Y
subRadius = ABS(R)
RadiusError = -subRadius
X = subRadius
Y = 0
IF subRadius = 0 THEN PSET ( CX, CY ) : EXIT SUB
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
LINE ( CX - X, CY ) TO ( CX + X, CY ), , BF
WHILE X > Y
RadiusError = RadiusError + Y * 2 + 1
IF RadiusError >= 0 THEN
IF X <> Y + 1 THEN
LINE ( CX - Y, CY - X ) TO ( CX + Y, CY - X ), , BF
LINE ( CX - Y, CY + X ) TO ( CX + Y, CY + X ), , BF
END IF
X = X - 1
RadiusError = RadiusError - X * 2
END IF
Y = Y + 1
LINE ( CX - X, CY - Y ) TO ( CX + X, CY - Y ), , BF
LINE ( CX - X, CY + Y ) TO ( CX + X, CY + Y ), , BF
WEND
END SUB
SUB fEllipse(CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG)
DIM scale AS SINGLE, x AS LONG, y AS LONG
scale = yRadius / xRadius
LINE ( CX, CY - yRadius ) TO ( CX, CY + yRadius ), , BF
FOR x = 1 TO xRadius
y = scale * SQR( xRadius * xRadius - x * x )
LINE ( CX + x, CY - y ) TO ( CX + x, CY + y ), , BF
LINE ( CX - x, CY - y ) TO ( CX - x, CY + y ), , BF
NEXT
END SUB